Author Sticky: Post Working Scripts Here
Doppleganger Posted: Tuesday, 25 June 06:47AM
Here's a script I ended up putting together for my roomate.. He wanted to be able to have a row of spike-trap-type effects that would trigger off one after another, continuously, and damage anyone unfortunate enough to get in their way.

The code is currently still a little messy, especially the actual effect/damage code (since I just wrapped my code around his). If anyone can improve on it, please do!

The way I used this was to create a row of invisible objects, named something like "MyTrapTest", "MyTrapTest0", "MyTrapTest1", "MyTrapTest2", etc. Then I set this script to the OnHeartBeat of the first object:

NWScript:
////////////////////////////

/// dop_startrowtrap

/// Purpose: Heartbeat script that initializes and starts a row of spike traps

///            marked by objects

/// Use:

///     1. Create one object with a unique tag in the area where the traps should be

///     2. Set the OnHeartbeat of this trap to this script, and the OnUserEvent to

///          the dop_runrowtraps script

///     3. Create a row of objects with tag set to the tag of the first object followed

///          by a number (i.e., if first object is "MyRowTrap", objects should be

///          "MyRowTrap0", "MyRowTrap1", "MyRowTrap2", etc.)

///     4. If necessary, tweak the DelayCommand value in dop_runrowtraps.

/// Author: Dopple (dopple@why-bother-me.com)

////////////////////////////

void main()

{

   // Only perform actions once.. This script should probably go in the area OnEntered

   //   script instead, but for now...

   if(GetLocalInt(OBJECT_SELF, "already_triggered") != 1)

   {

      // Get the name of the object this script is running on

      string sMyBaseName = GetTag(OBJECT_SELF);

      // Set a local integer on the object to hold the current object to act on

      SetLocalInt(OBJECT_SELF, "CurrentTrap", 0);

      // Find out how many objects are in the row

      int nCount = 0;

      while(GetIsObjectValid( GetObjectByTag( sMyBaseName + IntToString(nCount))))

      {

         nCount++;

      }

      // and set a local int on the object to hold that number

      SetLocalInt(OBJECT_SELF, "MaxTraps", nCount - 1);

      // Remember that we've done this once

      SetLocalInt(OBJECT_SELF, "already_triggered", 1);

      // Signal an event on ourself

      SignalEvent(OBJECT_SELF, EventUserDefined(0));

   }

}



And this script to the OnUserDefined of the first object:

NWScript:
////////////////////////////

/// dop_runrowtraps

/// Purpose: OnUserDefined script that runs a row of spike traps

///            marked by objects

/// Author: Dopple (dopple@why-bother-me.com)

////////////////////////////

void main()

{

   // Get name of the current object

   string sMyBaseName = GetTag(OBJECT_SELF);

   // Find out which location we're working on from the local variable on the object

   int nCurrent = GetLocalInt(OBJECT_SELF, "CurrentTrap");

   // Find out the max locations

   int nMax = GetLocalInt(OBJECT_SELF, "MaxTraps");

   object oTarget = GetFirstObjectInShape(SHAPE_CUBE, 0.5, GetLocation( GetObjectByTag(sMyBaseName + IntToString(nCurrent))), FALSE, OBJECT_TYPE_CREATURE);

   effect eDam = EffectDamage(d6(2), DAMAGE_TYPE_PIERCING);

   effect eVis = EffectVisualEffect(253);

   ApplyEffectAtLocation( DURATION_TYPE_INSTANT, eVis, GetLocation( GetObjectByTag(sMyBaseName + IntToString(nCurrent))));

// While loop commented out until we know how to do GetNextObjectInShape() correctly

//   while(oTarget != OBJECT_INVALID)

//   {

//      SpeakString(GetName(oTarget));

      if(GetIsPC(oTarget))

      {

         int nAC = GetAC(oTarget);

         //Make attack roll

         int nRoll = d20() + 11;

         if (nRoll > 0)

         {

            ApplyEffectToObject( DURATION_TYPE_INSTANT, eDam, oTarget);

         }

      }

//      object oTarget = GetNextObjectInShape( SHAPE_CUBE, 0.5, GetLocation( GetObjectByTag(sMyBaseName + IntToString(nCurrent))), FALSE, OBJECT_TYPE_CREATURE);

//   }

   // Move to the next one, or loop around if need be

   nCurrent++;

   if(nCurrent > nMax) { nCurrent = 0; }

   // Set the new current location

   SetLocalInt(OBJECT_SELF, "CurrentTrap", nCurrent);

   // Signal the next in the row

   DelayCommand(2.0, SignalEvent( GetObjectByTag(sMyBaseName), EventUserDefined(0)));

}



I think any object with both an OnHeartBeat and an OnUserDefined script could be used as locations for the traps, but I haven't tested with anything other than an invisible object yet.

[Edit]
Ye gads, just after posting this, I realized that it would only affect player characters, not npcs and such. Gonna have to figure out a way to fix that... my roomate's code originally used GetNearestCreature, but I changed it to the current form because it wasn't finding a target correctly when I started using invisible objects in place of trigger spots.
[/Edit]
_________________
Morituri Nolumus Mori!